﻿using eLoan.Models;
using GsmLink;
using GsmLink.Comm;
using System;
using System.IO.Ports;
using System.Linq;
using System.Windows.Forms;
using System.Collections.Generic;
using System.IO;
using System.Threading;



namespace Notification
{
    public partial class Notification : Form
    {
        public Notification()
        {
            InitializeComponent();
        }

        private void Notification_Load(object sender, EventArgs e)
        {
            PopulateBranches();
            PopulateNotices();

            btnSendDelayed.Enabled = false;
            btnSendDelinquent.Enabled = false;
            btnSendRenewal.Enabled = false;
            btnSendProspect.Enabled = false;

            btnStartModem.Enabled = true;
            btnStopModem.Enabled = false;
        }

        private void PopulateBranches()
        {
            var db = new DatabaseContext();
            var branches = db.Branches.ToList();

            cboBranch.DataSource = branches;
            cboBranch.ValueMember = "BranchCode";
            cboBranch.DisplayMember = "BranchName";

            PopulateAgents(cboBranch.SelectedValue.ToString());

            db.Dispose();
        }

        private void PopulateNotices()
        {
            var db = new DatabaseContext();

            var notices = db.Notifications.ToList();
            var notices1 = notices;
            var notices2 = notices;
            var notices3 = notices;
            var notices4 = notices;

            cboNoticeDelayed.DataSource = notices1;
            cboNoticeDelayed.ValueMember = "ID";
            cboNoticeDelayed.DisplayMember = "NotificationName";

            cboNoticeDelinquent.DataSource = notices2;
            cboNoticeDelinquent.ValueMember = "ID";
            cboNoticeDelinquent.DisplayMember = "NotificationName";

            cboNoticeRenewal.DataSource = notices3;
            cboNoticeRenewal.ValueMember = "ID";
            cboNoticeRenewal.DisplayMember = "NotificationName";

            cboNoticeProspect.DataSource = notices4;
            cboNoticeProspect.ValueMember = "ID";
            cboNoticeProspect.DisplayMember = "NotificationName";

            db.Dispose();
        }

        private void PopulateAgents(string branchCode)
        {
            var db = new DatabaseContext();
            var agents = db.Agents.Where(w => w.BranchCode == branchCode).ToList();

            cboAgent.DataSource = agents;
            cboAgent.ValueMember = "ID";
            cboAgent.DisplayMember = "AgentName";

            db.Dispose();
        }

        private void cboBranch_SelectedIndexChanged(object sender, EventArgs e)
        {
            var branchCode = ((ComboBox)sender).SelectedValue.ToString();
            PopulateAgents(branchCode);
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            PopulateGrids();
        }

        private void PopulateGrids()
        {
            var db = new DatabaseContext();
            var branchCode = cboBranch.SelectedValue != null ? cboBranch.SelectedValue.ToString() : string.Empty;
            var agentID = cboAgent.SelectedValue != null ? int.Parse(cboAgent.SelectedValue.ToString()) : 0;
            var list = WorkspaceHelper.GetLoansForNotificationList(DateTime.Now, branchCode, agentID);


            dgDelayed.AutoGenerateColumns = false;
            dgDelinquent.AutoGenerateColumns = false;
            dgCandidateForRenewal.AutoGenerateColumns = false;
            dgProspect.AutoGenerateColumns = false;

            dgDelayed.DataSource = list.Where(w => w.LoanStatus == AdministrationHelper.PenaltySort.Delayed.ToString()).ToList(); ;
            dgDelinquent.DataSource = list.Where(w => w.LoanStatus == AdministrationHelper.PenaltySort.Delinquent.ToString()).ToList();

            var forRenewal = db.Loans.Where(w => w.BranchCode == branchCode && w.StatusID == (int)AdministrationHelper.LoanStatus.Closed && w.RemarkID == (int)WorkspaceHelper.CloseLoanRemark.ConvinceForRenewal).ToList();
            dgCandidateForRenewal.DataSource = WorkspaceHelper.GetLoansForRenewalModel(forRenewal).ToList();

            var prospectList = db.Prospects.ToList();
            dgProspect.DataSource = WorkspaceHelper.GetLoanProspectModel(prospectList, branchCode, agentID);
        }

        static GsmDevice device = null;

        private void SendNotificationToList(string[] contacts, string message)
        {
            var countryCode = "63";

            for (var i = 0; i < contacts.Count(); i++)
            {
                if (message.Length <= 160)
                {
                    SmsMessage sms = new SmsMessage(countryCode + contacts[i], message);
                    sms.Tag = i + 1;
                    device.SendMessage(sms);
                }
                else if (message.Length + 5 > 160 && message.Length + 5 <= 320)
                {
                    string msg0, msg1 = string.Empty;

                    msg0 = "(1/2)" + message.Substring(0, 155);
                    SmsMessage sms0 = new SmsMessage(countryCode + contacts[i], msg0);
                    sms0.Tag = i + 1;
                    device.SendMessage(sms0);

                    msg1 = "(2/2)" + message.Substring(155, message.Length + 5 - 160);
                    SmsMessage sms1 = new SmsMessage(countryCode + contacts[i], msg1);
                    sms1.Tag = i + 1;
                    device.SendMessage(sms1);
                }
                else if (message.Length + 5 > 320 && message.Length + 5 <= 480)
                {
                    string msg0, msg1, msg2 = string.Empty;

                    msg0 = "(1/3)" + message.Substring(0, 155);
                    SmsMessage sms0 = new SmsMessage(countryCode + contacts[i], msg0);
                    sms0.Tag = i + 1;
                    device.SendMessage(sms0);

                    msg1 = "(2/3)" + message.Substring(155, 155);
                    SmsMessage sms1 = new SmsMessage(countryCode + contacts[i], msg1);
                    sms1.Tag = i + 1;
                    device.SendMessage(sms1);

                    msg2 = "(3/3)" + message.Substring(310, message.Length + 10 - 320);
                    SmsMessage sms2 = new SmsMessage(countryCode + contacts[i], msg2);
                    sms2.Tag = i + 1;
                    device.SendMessage(sms2);
                }
                else
                {
                    string msg0, msg1, msg2, msg3 = string.Empty;

                    msg0 = "(1/4)" + message.Substring(0, 155);
                    SmsMessage sms0 = new SmsMessage(countryCode + contacts[i], msg0);
                    sms0.Tag = i + 1;
                    device.SendMessage(sms0);

                    msg1 = "(2/4)" + message.Substring(155, 155);
                    SmsMessage sms1 = new SmsMessage(countryCode + contacts[i], msg1);
                    sms1.Tag = i + 2;
                    device.SendMessage(sms1);

                    msg2 = "3/4" + message.Substring(310, 155);
                    SmsMessage sms2 = new SmsMessage(countryCode + contacts[i], msg2);
                    sms2.Tag = i + 3;
                    device.SendMessage(sms2);

                    msg3 = "(4/4)" + message.Substring(465, message.Length + 15 - 480);
                    SmsMessage sms3 = new SmsMessage(countryCode + contacts[i], msg3);
                    sms3.Tag = i + 4;
                    device.SendMessage(sms3);
                }

            }
        }

        private void Connected(object sender, EventArgs e)
        {
            status.lstStatus.Items.Add(">> device connected.");
            status.lstStatus.Items.Add(string.Format(">> Manufacturer: {0}", device.Manufacturer));
            status.lstStatus.Items.Add(string.Format(">> Model: {0}", device.Model));
            status.lstStatus.Items.Add(string.Format(">> Serial #: {0}", device.SerialNumber));
            status.lstStatus.Items.Add(string.Format(">> Is using battery? {0}", device.IsUsingBattery));
            status.lstStatus.Items.Add(string.Format(">> Battery level: {0}", device.BatteryLevel));
            status.lstStatus.Items.Add(string.Format(">> Signal quality: {0}\n", device.SignalQuality));
            status.lstStatus.Items.Add(string.Empty);
        }

        private void Disconnected(object sender, EventArgs e)
        {
            status.lstStatus.Items.Add(">> device disconnected.");
            status.lstStatus.Items.Add(string.Empty);
        }

        private void BatteryLevelChanged(object sender, BatteryLevelChangedEventArgs e)
        {
            status.lstStatus.Items.Add(string.Format(">> battery level has changed: {0}", e.BatteryLevel));
            status.lstStatus.Items.Add(string.Empty);
        }

        private void SignalQualityChanged(object sender, SignalQualityChangedEventArgs e)
        {
            status.lstStatus.Items.Add(string.Format(">> device's signal quality has changed: {0}", e.SignalQuality));
            status.lstStatus.Items.Add(string.Empty);
        }

        private void MessageReceived(object sender, MessageReceivedEventArgs e)
        {
            int messageCount = e.Messages.GetLength(0);
            if (messageCount > 0)
            {
                status.lstStatus.Items.Add(string.Format(">> {0} message(s) received: ", messageCount));
                for (int i = 0; i < messageCount; i++)
                {
                    status.lstStatus.Items.Add(string.Format(">> Message # {0}", i + 1));
                    status.lstStatus.Items.Add(string.Format(">> Status: {0}", e.Messages[i].Status.ToString()));
                    status.lstStatus.Items.Add(string.Format(">> Sender: {0}", e.Messages[i].Sender));
                    status.lstStatus.Items.Add(string.Format(">> Time stamp: {0}", e.Messages[i].TimeStamp));
                    status.lstStatus.Items.Add(string.Format(">> Encoding: {0}", e.Messages[i].EncodingScheme.ToString()));

                    if (e.Messages[i].EncodingScheme == EncodingScheme.Text)
                    {
                        status.lstStatus.Items.Add(string.Format(">> Body: {0}", (string)e.Messages[i].Body));
                        status.lstStatus.Items.Add(string.Empty);
                    }
                    else
                    {
                        status.lstStatus.Items.Add(string.Format(">> Body: <cannot be displayed>"));
                        status.lstStatus.Items.Add(string.Empty);
                    }
                }
            }
        }

        private void SendMessageSucceeded(object sender, SendMessageResultEventArgs e)
        {
            status.lstStatus.Items.Add(string.Format(">> Successfully sent message to {0}", e.Message.Destination.ToString()));
            status.lstStatus.Items.Add(string.Empty);

            if (e.RetryCount > 0)
            {
                status.lstStatus.Items.Add(string.Format(">> after {0} retries", e.RetryCount));
                status.lstStatus.Items.Add(string.Empty);
            }

            device.NumberOfMessagesToSend--;
        }

        private void SendMessageFailed(object sender, SendMessageResultEventArgs e)
        {
            status.lstStatus.Items.Add(string.Format(">> Failed to send message #{0} after {1} retries.", e.Message.Tag.ToString(), e.RetryCount));
            status.lstStatus.Items.Add(string.Empty);
        }


        private NotificationStatus status;

        private void btnStartModem_Click(object sender, EventArgs e)
        {
            try
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;

                btnStartModem.Enabled = false;

                var portNames = SerialPort.GetPortNames();
                var modemPort = "";

                foreach (var portName in portNames)
                {
                    modemPort = portName;
                    break;
                }

                if (!string.IsNullOrEmpty(modemPort))
                {
                    status = new NotificationStatus();
                    status.Show();

                    device = new GsmDevice("GSMModem", CommDriverFactory.GetCommDriver(modemPort));
                    device.Connected += new EventHandler(Connected);
                    device.Disconnected += new EventHandler(Disconnected);
                    device.BatteryLevelChanged += new BatteryLevelChangedEventHandler(BatteryLevelChanged);
                    device.SignalQualityChanged += new SignalQualityChangedEventHandler(SignalQualityChanged);
                    device.MessageReceived += new MessageReceivedEventHandler(MessageReceived);
                    device.SendMessageSucceeded += new SendMessageResultEventHandler(SendMessageSucceeded);
                    device.SendMessageFailed += new SendMessageResultEventHandler(SendMessageFailed);

                    device.Start();

                    MessageBox.Show("Modem device is ready.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    btnStartModem.Enabled = false;
                    btnStopModem.Enabled = true;

                    btnSendDelayed.Enabled = true;
                    btnSendDelinquent.Enabled = true;
                    btnSendRenewal.Enabled = true;
                    btnSendProspect.Enabled = true;
                }
                else
                {
                    MessageBox.Show("Modem not found!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    btnStartModem.Enabled = true;
                    btnStopModem.Enabled = false;
                }

                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;
            }
            catch
            {
                device.Stop();
                MessageBox.Show("Modem not found!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                btnStartModem.Enabled = true;
                btnStopModem.Enabled = false;
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;
            }
        }

        private void btnSendDelayed_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
            SendDelayedNotice();
            dgDelayed.ClearSelection();
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;
        }

        private void SendDelayedNotice()
        {
            using (var db = new DatabaseContext())
            {
                int notice = 0;
                int.TryParse(cboNoticeDelayed.SelectedValue.ToString(), out notice);

                var msg = db.Notifications.Where(w => w.ID == notice).SingleOrDefault<eLoan.Models.Notification>().Message;

                foreach (DataGridViewRow item in dgDelayed.Rows)
                {
                    if (item.Selected)
                    {
                        var contacts = item.Cells["DelayedContactNumbers"].Value.ToString().Split(' ');
                        var message = msg
                                      .Replace("{0}", item.Cells["DelayedBorrowerName"].Value.ToString())
                                      .Replace("{1}", decimal.Parse(item.Cells["DelayedShortOver"].Value.ToString()).ToString("#,###,##0.00").Replace("-", ""))
                                      .Replace("{2}", DateTime.Now.ToString("MMMM dd, yyyy"));

                        SendNotificationToList(contacts, message);
                    }
                }
            }
        }

        private void btnSendDelinquent_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
            SendDelinquent();
            dgDelinquent.ClearSelection();
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;
        }

        private void SendDelinquent()
        {
            using (var db = new DatabaseContext())
            {
                int notice = 0;
                int.TryParse(cboNoticeDelinquent.SelectedValue.ToString(), out notice);

                var msgForDelinquent = db.Notifications.Where(w => w.ID == notice).SingleOrDefault<eLoan.Models.Notification>().Message;
                
                foreach (DataGridViewRow item in dgDelinquent.Rows)
                {
                    if (item.Selected)
                    {
                        var contacts = item.Cells["DelinquentContactNumbers"].Value.ToString().Split(' ');
                        var message = msgForDelinquent
                                    .Replace("{0}", item.Cells["DelinquentBorrowerName"].Value.ToString())
                                    .Replace("{1}", decimal.Parse(item.Cells["DelinquentShortOver"].Value.ToString()).ToString("#,###,##0.00").Replace("-", ""))
                                    .Replace("{2}", DateTime.Parse(item.Cells["DelinquentPaymentEndDate"].Value.ToString()).ToString("MMM dd, yyyy"));

                        SendNotificationToList(contacts, message);
                    }
                }
            }
        }

        private void btnSendRenewal_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
            SendRenewal();
            dgCandidateForRenewal.ClearSelection();
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;
        }

        private void SendRenewal()
        {
            using (var db = new DatabaseContext())
            {
                int notice = 0;
                int.TryParse(cboNoticeRenewal.SelectedValue.ToString(), out notice);

                var msg = db.Notifications.Where(w => w.ID == notice).SingleOrDefault<eLoan.Models.Notification>().Message;
                
                foreach (DataGridViewRow item in dgCandidateForRenewal.Rows)
                {
                    if (item.Selected)
                    {
                        var contacts = item.Cells["RenewalContactNumbers"].Value.ToString().Split(' ');
                        var message = msg.Replace("{0}", item.Cells["RenewalBorrowerName"].Value.ToString());

                        SendNotificationToList(contacts, message);
                    }
                }
            }
        }

        private void btnSendProspect_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
            SendProspect();
            dgProspect.ClearSelection();
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;
        }

        private void SendProspect()
        {
            using (var db = new DatabaseContext())
            {
                int notice = 0;
                int.TryParse(cboNoticeProspect.SelectedValue.ToString(), out notice);

                var msg = db.Notifications.Where(w => w.ID == notice).SingleOrDefault<eLoan.Models.Notification>().Message;

                foreach (DataGridViewRow item in dgProspect.Rows)
                {
                    if (item.Selected)
                    {
                        var contacts = item.Cells["ProspectContactNumbers"].Value.ToString().Split(' ');
                        var message = msg.Replace("{0}", item.Cells["ProspectName"].Value.ToString());

                        SendNotificationToList(contacts, message);
                    }
                }
            }
        }

        private void btnStopModem_Click(object sender, EventArgs e)
        {
            status.Close();
            device.Stop();

            btnStopModem.Enabled = false;
            btnStartModem.Enabled = true;

            btnSendDelayed.Enabled = false;
            btnSendDelinquent.Enabled = false;
            btnSendRenewal.Enabled = false;
            btnSendProspect.Enabled = false;
        }
    }
}
